/*-------------------------------------------------------------------------
 *
 * itemptr.h
 *	  POSTGRES 磁盘项指针的定义。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/itemptr.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef ITEMPTR_H
#define ITEMPTR_H

#include "storage/block.h"
#include "storage/off.h"

/*
 * ItemPointer:
 *
 * 这是一个指向已知文件的磁盘页内项目的指针
 * （例如，从索引到其父表的交叉链接）。
 * ip_blkid告诉我们哪个块，ip_posid告诉我们
 * linp（ItemIdData）数组中我们想要的条目。
 *
 * 注意：由于每个元组头和磁盘上的索引
 * 元组头中都有一个项目指针，因此非常重要的是不要浪费空间
 * 结构填充字节。 该结构设计为六个字节长
 * （包含三个int16字段），但某些编译器将将其填充为
 * 八个字节，除非被强制。 我们在可能的地方施加适当的说服力。
 * 如果您的编译器无法配合，您将浪费
 * 很多空间。
 */
typedef struct ItemPointerData
{
	BlockIdData ip_blkid;
	OffsetNumber ip_posid;
}

/* 如果编译器理解打包和对齐的指令，则使用这些 */
#if defined(pg_attribute_packed) && defined(pg_attribute_aligned)
			pg_attribute_packed()
			pg_attribute_aligned(2)
#endif
ItemPointerData;

typedef ItemPointerData *ItemPointer;

/* ----------------
 *		堆元组中使用的特殊值（t_ctid）
 * ----------------
 */

/*
 * 如果堆元组持有推测插入令牌而不是实际
 * TID，则ip_posid设置为SpecTokenOffsetNumber，令牌存储在
 * ip_blkid中。 SpecTokenOffsetNumber必须高于MaxOffsetNumber，以便
 * 能够与常规项目指针中的有效偏移量区分开。
 */
#define SpecTokenOffsetNumber		0xfffe

/*
 * 当元组通过更新移动到不同的分区时，旧元组版本的t_ctid
 * 设置为此魔法值。
 */
#define MovedPartitionsOffsetNumber 0xfffd
#define MovedPartitionsBlockNumber	InvalidBlockNumber


/* ----------------
 *		支持宏
 * ----------------
 */

/*
 * ItemPointerIsValid
 *		如果磁盘项目指针不为NULL则为真。
 */
#define ItemPointerIsValid(pointer) \
	((bool) (PointerIsValid(pointer) && ((pointer)->ip_posid != 0)))

/*
 * ItemPointerGetBlockNumberNoCheck
 *		返回磁盘项目指针的块号。
 */
#define ItemPointerGetBlockNumberNoCheck(pointer) \
( \
	BlockIdGetBlockNumber(&(pointer)->ip_blkid) \
)

/*
 * ItemPointerGetBlockNumber
 *		如上所述，但验证项目指针看起来有效。
 */
#define ItemPointerGetBlockNumber(pointer) \
( \
	AssertMacro(ItemPointerIsValid(pointer)), \
	ItemPointerGetBlockNumberNoCheck(pointer) \
)

/*
 * ItemPointerGetOffsetNumberNoCheck
 *		返回磁盘项目指针的偏移号。
 */
#define ItemPointerGetOffsetNumberNoCheck(pointer) \
( \
	(pointer)->ip_posid \
)

/*
 * ItemPointerGetOffsetNumber
 *		如上所述，但验证项目指针看起来有效。
 */
#define ItemPointerGetOffsetNumber(pointer) \
( \
	AssertMacro(ItemPointerIsValid(pointer)), \
	ItemPointerGetOffsetNumberNoCheck(pointer) \
)

/*
 * ItemPointerSet
 *		将磁盘项目指针设置为指定的块和偏移量。
 */
#define ItemPointerSet(pointer, blockNumber, offNum) \
( \
	AssertMacro(PointerIsValid(pointer)), \
	BlockIdSet(&((pointer)->ip_blkid), blockNumber), \
	(pointer)->ip_posid = offNum \
)

/*
 * ItemPointerSetBlockNumber
 *		将磁盘项目指针设置为指定的块。
 */
#define ItemPointerSetBlockNumber(pointer, blockNumber) \
( \
	AssertMacro(PointerIsValid(pointer)), \
	BlockIdSet(&((pointer)->ip_blkid), blockNumber) \
)

/*
 * ItemPointerSetOffsetNumber
 *		将磁盘项目指针设置为指定的偏移量。
 */
#define ItemPointerSetOffsetNumber(pointer, offsetNumber) \
( \
	AssertMacro(PointerIsValid(pointer)), \
	(pointer)->ip_posid = (offsetNumber) \
)

/*
 * ItemPointerCopy
 *		将一个磁盘项目指针的内容复制到另一个。
 *
 * 如果ItemPointer中有填充，则需要以不同方式处理
 * 因为它被用作哈希键。
 */
#define ItemPointerCopy(fromPointer, toPointer) \
( \
	AssertMacro(PointerIsValid(toPointer)), \
	AssertMacro(PointerIsValid(fromPointer)), \
	*(toPointer) = *(fromPointer) \
)

/*
 * ItemPointerSetInvalid
 *		将磁盘项目指针设置为无效。
 */
#define ItemPointerSetInvalid(pointer) \
( \
	AssertMacro(PointerIsValid(pointer)), \
	BlockIdSet(&((pointer)->ip_blkid), InvalidBlockNumber), \
	(pointer)->ip_posid = InvalidOffsetNumber \
)

/*
 * ItemPointerIndicatesMovedPartitions
 *		如果块号指示元组已移动到另一个
 *		分区，则为真。
 */
#define ItemPointerIndicatesMovedPartitions(pointer) \
( \
	ItemPointerGetOffsetNumber(pointer) == MovedPartitionsOffsetNumber && \
	ItemPointerGetBlockNumberNoCheck(pointer) == MovedPartitionsBlockNumber \
)

/*
 * ItemPointerSetMovedPartitions
 *		指示项目指针引用的项目已移动到
 *		不同的分区。
 */
#define ItemPointerSetMovedPartitions(pointer) \
	ItemPointerSet((pointer), MovedPartitionsBlockNumber, MovedPartitionsOffsetNumber)

/* ----------------
 *		外部
 * ----------------
 */

extern bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2);
extern int32 ItemPointerCompare(ItemPointer arg1, ItemPointer arg2);
extern void ItemPointerInc(ItemPointer pointer);
extern void ItemPointerDec(ItemPointer pointer);

#endif							/* ITEMPTR_H */
